// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

// A server to receive HttpRequest and send back HttpResponse.

#include <turbo/flags/flag.h>
#include <krpc/utility/logging.h>
#include <krpc/rpc/server.h>
#include <krpc/rpc/restful.h>
#include <krpc/json2pb/pb_to_json.h>
#include <krpc/rpc/restful_service.h>

TURBO_FLAG(int32_t, port, 8010, "TCP Port of this server");
TURBO_FLAG(int32_t, idle_timeout_s, -1, "Connection will be closed if there is no "
             "read/write operations during the last `idle_timeout_s'");

TURBO_FLAG(std::string, certificate, "cert.pem", "Certificate file path to enable SSL");
TURBO_FLAG(std::string, private_key, "key.pem", "Private key file path to enable SSL");
TURBO_FLAG(std::string, ciphers, "", "Cipher suite used for SSL connections");

int main(int argc, char* argv[]) {
    auto *run_app = turbo::Servlet::instance().run_app();
    run_app->add_option("--port", FLAGS_port, FLAGS_port.help());
    run_app->add_option("--idle_timeout_s", FLAGS_idle_timeout_s, FLAGS_idle_timeout_s.help());
    run_app->add_option("--certificate", FLAGS_certificate, FLAGS_certificate.help());
    run_app->add_option("--private_key", FLAGS_private_key, FLAGS_private_key.help());
    run_app->add_option("--ciphers", FLAGS_ciphers, FLAGS_ciphers.help());
    auto [exit, ret] = turbo::Servlet::instance().run(argc, argv);
    if (exit) {
        return ret;
    }
    // Generally you only need one Server.
    krpc::Server server;

    auto *ins = krpc::RestfulService::instance();
    ins->set_processor("/hello", [](const krpc::RestfulRequest* req, krpc::RestfulResponse*res) -> void {
        res->set_status_code(200);
        res->set_content_type("text/plain");
        res->append_body("Hello, world!");
    });
    ins->set_processor("/world", [](const krpc::RestfulRequest* req, krpc::RestfulResponse*res) -> void {
        res->set_status_code(200);
        res->set_content_type("text/plain");
        auto upath = req->unresolved_path();
        if(upath.empty()) {
            upath = "root";
        }
        res->append_body("Hello, world!-->> ");
        res->append_body(upath);
    }, true);

    // Start the server.
    krpc::ServerOptions options;
    options.idle_timeout_sec = turbo::get_flag(FLAGS_idle_timeout_s);
    options.mutable_ssl_options()->default_cert.certificate = turbo::get_flag(FLAGS_certificate);
    options.mutable_ssl_options()->default_cert.private_key = turbo::get_flag(FLAGS_private_key);
    options.mutable_ssl_options()->ciphers = turbo::get_flag(FLAGS_ciphers);
    if (server.Start(turbo::get_flag(FLAGS_port), &options) != 0) {
        LOG(ERROR) << "Fail to start HttpServer";
        return -1;
    }

    // Wait until Ctrl-C is pressed, then Stop() and Join() the server.
    server.RunUntilAskedToQuit();
    return 0;
}
